package cn.airnan.dg.utils;

import cn.airnan.dg.configs.Global;
import cn.airnan.dg.entity.Player;
import cn.airnan.dg.entity.Room;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
@Slf4j
@ServerEndpoint("/websocket/{playerId}/{roomId}")
public class WebSocket {


    /**
     * 加入房间时触发WebSocket事件
     *
     * @param session  当前会话
     * @param playerId 玩家id
     * @param roomId   房间id
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "playerId") String playerId, @PathParam(value = "roomId") String roomId) {
        try {
            // 将会话添加到会话列表
            Global.SESSIONS.add(session);
            // 将会话添加到连接池
            Global.SESSION_POOL.put(playerId, session);
            // 将会话与玩家绑定
            Player player = Global.PLAYERS.get(playerId);
            if (player != null) {
                player.setSession(session);
            }

            // 加入房间
            Room room = Global.ROOMS.get(roomId);
            if (room != null) {
                room.addPlayer(player);
            }

            // 通知其他玩家有新玩家加入
            if (room != null) {
                String message = "玩家【" + playerId + "】加入了房间";
                room.sendMessage(Global.MSG_TYPE_ROOM_MSG, playerId, message);
                room.sendMessage(Global.MSG_TYPE_ROOM_CHAT, playerId, "系统："+message);
            }

            log.info("【加入房间】玩家 {} 进入房间 {}，房间人数为：{}", playerId, roomId, Global.SESSIONS.size());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @OnClose
    public void onClose(Session session) {
        try {
            // 从会话列表中移除关闭的会话
            Global.SESSIONS.remove(session);
            // 从连接池中移除关闭的会话
            String playerIdToRemove = null;
            for (Map.Entry<String, Session> entry : Global.SESSION_POOL.entrySet()) {
                if (entry.getValue().equals(session)) {
                    playerIdToRemove = entry.getKey();
                    break;
                }
            }
            if (playerIdToRemove != null) {
                Global.SESSION_POOL.remove(playerIdToRemove);
            }
            String playerId = "";
            // 清除玩家与会话的绑定
            for (Player player : Global.PLAYERS.values()) {
                if (player.getSession() != null && player.getSession().equals(session)) {
                    player.setSession(null);
                    playerId = player.getId();
                    break;
                }
            }
            // 从房间中移除玩家
            for (Room room : Global.ROOMS.values()) {
                room.removePlayerById(playerId);
                String message = "玩家【" + playerId + "】退出了游戏，房间人数为：" + room.getPlayers().size();
                room.sendMessage(Global.MSG_TYPE_ROOM_MSG, playerId, message);
                room.sendMessage(Global.MSG_TYPE_ROOM_CHAT, playerId, "系统："+message);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @OnMessage
    public void onMessage(String message) {
//        log.info("【WebSocket消息】收到客户端消息：{}", message);
        try {
            // 解析消息为 SocketMsg 结构体
            SocketMsg<String> socketMsg = JSON.parseObject(message, new TypeReference<>() {
            });
            // 匹配房间并转发消息
            Global.ROOMS.get(socketMsg.getRoomId()).sendMessage(socketMsg.getType(), socketMsg.getPlayerId(), socketMsg.getData());
        } catch (Exception e) {
            log.error("解析消息失败：{}", message);
        }
    }

    /**
     * 此为广播消息
     *
     * @param message 消息
     */
    public static void sendAllMessage(String message) {
        for (Session session : Global.SESSIONS) {
            try {
                if (session.isOpen()) {
                    session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    /**
     * 此为单点消息
     *
     * @param playerId 用户编号
     * @param message  消息
     */
    public static void sendOneMessage(String playerId, String message) {
        Session session = Global.SESSION_POOL.get(playerId);
        if (session != null && session.isOpen()) {
            try {
                synchronized (session) {
                    session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    /**
     * 此为单点消息(多人)
     *
     * @param playerIds 用户编号列表
     * @param message   消息
     */
    public static void sendMoreMessage(String[] playerIds, String message) {
        for (String playerId : playerIds) {
            Session session = Global.SESSION_POOL.get(playerId);
            if (session != null && session.isOpen()) {
                try {
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
        }
    }

    public static Integer getOnLine() {
        return Global.SESSION_POOL.size();
    }
}

